home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / vbcc / machines / amigappc / ppcrun / ppcrun.c < prev   
Encoding:
C/C++ Source or Header  |  1998-06-24  |  9.1 KB  |  302 lines

  1. /*
  2. ** PPCRun
  3. **
  4. ** Run an ELF object under AmigaOS as a new PowerPC task.
  5. **
  6. ** V0.9a 24-Dec-97 vb
  7. **       Modified to use inline library calls
  8. ** V0.9  23-Dec-97 phx
  9. **       To be compatible with elfrun and SAS/C-ppc, pass the command
  10. **       line in GPR3, instead argc/argv in GPR3/4.
  11. **       PPCRun is compiled with vbcc's minimal startup code to get
  12. **       direct access to the command line.
  13. **       Removed all debugging output.
  14. **       Successfully tested with ppc.library V45.2. Removing a crashed
  15. **       task with CTRL-D works perfectly now. But I'm not sure, if I
  16. **       fixed a bug or
  17. ** V0.4  18-Oct-97 phx
  18. **       Close(errfh) was missing. Included a help text.
  19. ** V0.3  11-Oct-97 phx
  20. **       Define DEBUG for debugging output.
  21. ** V0.2  07-Oct-97 phx
  22. **       fixed some infinite loops :)
  23. ** V0.1  04-Oct-97 phx
  24. **       created
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <exec/types.h>
  29. #include <exec/execbase.h>
  30. #include <exec/memory.h>
  31. #include <exec/libraries.h>
  32. #include <exec/ports.h>
  33. #include <dos/dos.h>
  34. #include <dos/dosextens.h>
  35. #include <utility/tagitem.h>
  36. #include <ppclib/tasks.h>
  37. #include <ppclib/message.h>
  38. #include <proto/exec.h>
  39. #include <proto/dos.h>
  40. #include <proto/ppc.h>
  41. /*
  42. #include <clib/exec_protos.h>
  43. #include <clib/dos_protos.h>
  44. #include <powerup/clib/ppc_protos.h>
  45. */
  46. #define VERSION "PPCRun 0.9a (24.12.97)"
  47. #define PPCLIBVER 44
  48. #define PPCDEFPRI 0
  49.  
  50. #define MSGID_EXIT 0x44584954
  51.  
  52.  
  53. struct StartupData {
  54.   APTR M68kPort;  /* the PowerPC task can send messages to this port */
  55.   BPTR std_in;    /* standard input handle */
  56.   BPTR std_out;   /* standard output handle */
  57.   BPTR std_err;   /* standard error handle */
  58.   LONG retCode;   /* here we will find the return code from the PPC task */
  59.   ULONG flags;    /* additional flags (currently unused) */
  60. };
  61.  
  62.  
  63. extern struct ExecBase *SysBase;
  64.  
  65. struct DOSBase *DOSBase = NULL;
  66. struct Library *PPCLibBase = NULL;
  67.  
  68. static const char *ppcrun = "PPCRun";
  69. static const char *version = "$VER: " VERSION "\r\n";
  70. static const char *ppclibname = "ppc.library";
  71.  
  72.  
  73.  
  74. static char *nextarg(char *p)
  75. /* get pointer to next argument in command line */
  76. {
  77.   while (*p<=' ' && *p!=0)
  78.     p++;
  79.   if (*p == 0)
  80.     return (NULL);
  81.   return (p);
  82. }
  83.  
  84.  
  85. static char *skiparg(char *p)
  86. /* find end of argument */
  87. {
  88.   char c;
  89.  
  90.   if (*p != '\"') {
  91.     while (*p > ' ')
  92.       p++;
  93.   }
  94.   else {
  95.     p++;
  96.     do
  97.       c = *p++;
  98.     while (c!='\"' && c!=0);
  99.     if (c==0)
  100.       p--;
  101.   }
  102.   return (p);
  103. }
  104.  
  105.  
  106. int main(char *cmdline)
  107. {
  108.   APTR elfobject,startupmsg,ppctask,ppcmsg;
  109.   BPTR errfh=0;
  110.   char *taskname=NULL,*args=NULL;
  111.   struct MsgPort *m68kport; /* not documented as real MsgPort, but I hope.. */
  112.   int rc = 10;
  113.   struct StartupData *sd;  /* data delivered with startup message */
  114.   char c,*elfname,*p;
  115.   ULONG argsize,sigmask=0;
  116.   ULONG sigppc;  /* signal mask: PPC message coming in */
  117.   struct Process *pr;
  118.  
  119.   static struct TagItem porttags[] = {
  120.     TAG_END
  121.   };
  122.   static struct TagItem tasktags[] = {
  123.     PPCTASKTAG_NAME,0,
  124.     PPCTASKTAG_ARG1,0,
  125.     PPCTASKTAG_MSGPORT,TRUE,
  126.     PPCTASKTAG_STARTUP_MSG,0,
  127.     PPCTASKTAG_STARTUP_MSGDATA,0,
  128.     PPCTASKTAG_STARTUP_MSGLENGTH,0,
  129.     PPCTASKTAG_STARTUP_MSGID,0,
  130.     PPCTASKTAG_STACKSIZE,0,
  131.     PPCTASKTAG_PRIORITY,PPCDEFPRI,
  132.     TAG_END
  133.   };
  134.  
  135.  
  136.   if (SysBase->LibNode.lib_Version < 36)  /* We need OS2.0! */
  137.     exit (15);
  138.   if (!(DOSBase = (struct DOSBase *)OpenLibrary("dos.library",36)))
  139.     exit (15);
  140.  
  141.   if (*cmdline==0 || *cmdline=='?') {
  142.     Printf(VERSION "\n(c)1997 by Frank Wille\n\nUsage: "
  143.            "%s <ELF object> [<aguments> ...]\n",ppcrun);
  144.     rc = 5;
  145.   }
  146.  
  147.   else {
  148.     if (PPCLibBase = OpenLibrary((STRPTR)ppclibname,PPCLIBVER)) {
  149.       if (sd = (struct StartupData *)
  150.           PPCAllocVec(sizeof(struct StartupData),MEMF_CLEAR|MEMF_PUBLIC)) {
  151.         sd->std_in = Input();
  152.         sd->std_out = Output();
  153.         if (errfh = Open("CONSOLE:",MODE_NEWFILE))
  154.           sd->std_err = errfh;
  155.         else
  156.           sd->std_err = sd->std_out;
  157.  
  158.         /* parse options and determine name of ELF object */
  159.         while (cmdline = nextarg(cmdline)) {
  160.           if (*cmdline != '-')
  161.             break;
  162.           cmdline++;
  163.           switch (*cmdline++) {
  164.             /* here we could check for options - currently unused... */
  165.             default:
  166.               Printf("%s: Unrecognized option -%lc!\n",
  167.                      ppcrun,(ULONG)*(--cmdline));
  168.               cmdline = skiparg(cmdline);
  169.               break;
  170.           }
  171.         }
  172.         if (cmdline) {
  173.           elfname = cmdline;
  174.           p = skiparg(cmdline);
  175.           c = *p;
  176.           if (*elfname == '\"') {  /* file name in quotes? */
  177.             elfname++;
  178.             if (*(p-1) == '\"') {
  179.               c = '\"';
  180.               p--;
  181.             }
  182.           }
  183.           *p = 0;
  184.  
  185.           if (elfobject = PPCLoadObject(elfname)) {
  186.             /* copy command line for PPC task */
  187.             argsize = (p - elfname) + 1;
  188.             if (taskname = (char *)AllocVec(argsize,MEMF_ANY))
  189.               CopyMem(elfname,taskname,argsize);
  190.             *p = c;
  191.             p = cmdline;
  192.             argsize = 0;
  193.             do
  194.               argsize++;
  195.             while (*p++);
  196.             if (args = (char *)PPCAllocVec(argsize,MEMF_ANY))
  197.               CopyMem(cmdline,args,argsize);
  198.  
  199.             /* create M68k message port and startup message */
  200.             if (m68kport = (struct MsgPort *)PPCCreatePort(porttags)) {
  201.               sigppc = 1 << m68kport->mp_SigBit;
  202.  
  203.               if (startupmsg =
  204.                   PPCCreateMessage(m68kport,sizeof(struct StartupData))) {
  205.                 sd->M68kPort = m68kport;
  206.  
  207.                 /* start PowerPC task */
  208.                 tasktags[0].ti_Data = (ULONG)taskname;  /* task name */
  209.                 tasktags[1].ti_Data = (ULONG)args;      /* arg1 - cmdline */
  210.                 tasktags[3].ti_Data = (ULONG)startupmsg;
  211.                 tasktags[4].ti_Data = (ULONG)sd;
  212.                 tasktags[5].ti_Data = sizeof(struct StartupData);
  213.                 tasktags[6].ti_Data = MSGID_EXIT;
  214.                 /* determine stack size for PowerPC */
  215.                 pr = (struct Process *)FindTask(NULL);
  216.                 if (pr->pr_Task.tc_Node.ln_Type == NT_PROCESS && pr->pr_CLI)
  217.                   tasktags[7].ti_Data = *(ULONG *)pr->pr_ReturnAddr;
  218.                 else
  219.                   tasktags[7].ti_Data = (ULONG)((char *)pr->pr_Task.tc_SPUpper
  220.                                         - (char *)pr->pr_Task.tc_SPLower);
  221.                 CacheClearU();
  222.                 if (ppctask = PPCCreateTask(elfobject,tasktags)) {
  223.  
  224.                   for (;;) {
  225.                     ULONG mid;
  226.                     BOOL quit;
  227.                     struct StartupData *ppcsd;
  228.  
  229.                     sigmask = Wait(sigppc |
  230.                                    SIGBREAKF_CTRL_C |
  231.                                    SIGBREAKF_CTRL_D);
  232.  
  233.                     /* Message from PPC task */
  234.                     if (sigmask & sigppc) {
  235.                       quit = FALSE;
  236.                       while (ppcmsg = PPCGetMessage(m68kport)) {
  237.                         if (mid = PPCGetMessageAttr(ppcmsg,PPCMSGTAG_MSGID)
  238.                             == MSGID_EXIT) {
  239.                           ppcsd = (struct StartupData *)
  240.                                   PPCGetMessageAttr(ppcmsg,PPCMSGTAG_DATA);
  241.                           rc = ppcsd->retCode;  /* set return code */
  242.                           quit = TRUE;
  243.                           break;
  244.                         }
  245.                         else {  /* received unknown message from PPC task */
  246.                           Printf("PPC task sent unknown message "
  247.                                  "with id = %ld.\n",mid);
  248.                           PPCReplyMessage(ppcmsg);
  249.                         }
  250.                       }
  251.                       if (quit)  /* PPC task has finished */
  252.                         break;
  253.                     }
  254.  
  255.                     /* CTRL-D immediately kills the PPC task */
  256.                     if (sigmask & SIGBREAKF_CTRL_D) {
  257.                       PPCDeleteTask(ppctask);
  258.                       break;
  259.                     }
  260.  
  261.                     /* CTRL-C is passed on to the PPC task */
  262.                     if (sigmask & SIGBREAKF_CTRL_C) {
  263.                       SetSignal(0,SIGBREAKF_CTRL_C);
  264.                       PPCSignalTask(ppctask,SIGBREAKF_CTRL_C);
  265.                     }
  266.                   }
  267.  
  268.                 }
  269.                 else
  270.                   Printf("Unable to create PPC task.\n");
  271.                 PPCDeleteMessage(startupmsg);
  272.               }
  273.               else
  274.                 Printf("Can't create startup message for PPC task.\n");
  275.               PPCDeletePort(m68kport);
  276.             }
  277.             else
  278.               Printf("Can't create MsgPort for PPC-messages.\n");
  279.             PPCFreeVec(args);
  280.             FreeVec(taskname);
  281.             PPCUnLoadObject(elfobject);
  282.           }
  283.           else
  284.             Printf("%s: Unknown command.\n",elfname);
  285.         }
  286.         else
  287.           Printf("Missing argument <ELF object>!\n");
  288.         if (errfh)
  289.           Close(errfh);
  290.         PPCFreeVec(sd);
  291.       }
  292.       else
  293.         Printf("Not enough memory for startup data.\n");
  294.       CloseLibrary(PPCLibBase);
  295.     }
  296.     else
  297.       Printf("Can't open %s V%ld.\n",ppclibname,PPCLIBVER);
  298.   }
  299.   CloseLibrary((struct Library *)DOSBase);
  300.   exit(rc);
  301. }
  302.